﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using RRRSRoguelike.Entities;
using RRRSRoguelike.Managers;

namespace RRRSRoguelike.Helpers.Visualizer
{
	/// <summary>
	/// The visualizer repaints the screen using the current dungeon layer and the known position of the elements displayed in the camera.
	/// </summary>
	public class Visualizer
	{

		#region variables
		//Where to start drawing dungeon 0,0
		public Point StartPoint;

		public Camera Camera;

		public Layer layer;

		#endregion

		#region constructors
		public Visualizer()
		{
			//Sets TopLeft of dungeon centered in console.
			StartPoint.X = Console.WindowWidth / 2 - Constants.DungeonWidth / 2;
			//StartPointY = Console.WindowHeight / 2 - Constants.DungeonHeight / 2 -1;
			StartPoint.Y = 5;

			Camera = new Camera(Constants.DungeonWidth, Constants.DungeonHeight);
			layer = new Layer();
		}
		#endregion

		#region methods
		public static Point GetScreenCenter()
		{
			return new Point(Console.WindowWidth / 2, Constants.DungeonHeight / 2);
		}

		public static int GetScreenWidth()
		{
			return Console.WindowWidth;
		}

		public static int GetScreenHeight()
		{
			return Console.WindowHeight;
		}

		public void Visualize(DungeonLevel dungeonLevel, bool drawPanel)
		{
			//Console.Clear();
			//Repeating this makes sure the console has not been resized.
			ConsoleSpecific.SetConsoleSize(Constants.ConsoleWidth, Constants.ConsoleHeight);


			Draw(dungeonLevel, new Point(StartPoint.X, StartPoint.Y + 1));

		}

		/// <summary>
		/// Wraps the console write line should make it easier to port later.
		/// </summary>
		/// <param name="text"></param>
		/// <param name="color"></param>
		public static void WriteLine(string text, ConsoleColor color = ConsoleColor.White, ConsoleColor background = ConsoleColor.Black)
		{
			Console.BackgroundColor = background;
			Console.ForegroundColor = color;
			Console.WriteLine(text);
			Console.BackgroundColor = ConsoleColor.Black;
		}

		/// <summary>
		/// Uses the SetCursorPosition to place text.
		/// </summary>
		/// <param name="text"></param>
		/// <param name="position"></param>
		public static void WriteLine(string text, Point position, ConsoleColor color = ConsoleColor.White, ConsoleColor background = ConsoleColor.Black)
		{
			if (position.X < Console.WindowWidth && position.Y < Console.WindowHeight)
			{
				Console.SetCursorPosition(position.X, position.Y);

				WriteLine(text, color, background);
			}
		}

		public static void WriteMultiLine(string text, Point position, ConsoleColor color = ConsoleColor.White, StringSplitOptions options = StringSplitOptions.None)
		{
			string[] lineArray = text.Split("\r\n".ToArray(), options);


			foreach (string s in lineArray)
			{
				if (s != "")
				{
					WriteLine(s, position, color);
					position.Y++;
				}
			}
		}

		public static void WriteLine(DungeonSquare dungeonSquare, Point position)
		{
			ConsoleColor tempBackground = dungeonSquare.background;

			Console.SetCursorPosition(position.X, position.Y);

			WriteLine(dungeonSquare.character, dungeonSquare.color, tempBackground);


		}

		/// <summary>
		/// Accepts text and a width adds spaces to text to centralize.
		/// Text should be one line and shorter than width, otherwise trims to fit one line.
		/// </summary>
		/// <param name="text">one line of text less than width</param>
		/// <param name="width">width of line in characters</param>
		/// <returns>a centralized text or trimmed text</returns>
		public static string CentralizeText(string text, int width)
		{
			//Centralize
			if (text.Length < width)
			{
				StringBuilder sb = new StringBuilder();
				sb.Append(' ', (width - text.Length) / 2);
				sb.Append(text);
				//sb.Append(' ', (width - text.Length) / 2);

				text = sb.ToString();
			}
			//Chop
			else if (text.Length > width)
				text = text.Remove(width);

			return text;
		}

		public static StringBuilder BuildString(string text, int lineWidth = 60)
		{
			List<string> lines;
			lines = new List<string>();

			string[] lineArray = text.Split("\r\n".ToArray(), StringSplitOptions.RemoveEmptyEntries);


			StringBuilder line = new StringBuilder();


			foreach (string arrayLine in lineArray)
			{
				string[] wordArray = arrayLine.Split(' ');
				foreach (string word in wordArray)
				{
					Wrap(lines, line, word, lineWidth);
				}
				lines.Add(line.ToString());
				line.Clear();
			}

			StringBuilder output;
			output = new StringBuilder();
			foreach (string l in lines)
			{
				output.Append(l);
				output.Append("\r\n");
			}

			return output;
		}

		private static void Wrap(List<string> lines, StringBuilder line, string word, int lineWidth)
		{
			if (line.Length + word.Length >= lineWidth)
			{
				lines.Add(line.ToString());
				line.Clear();
				line.Append(word + " ");
			}
			else
				line.Append(word + " ");
		}

		public void Flash(Tile tile, int number = 10, long delay = 100)
		{
			long Timer;



			for (int i = 0; i < number; i++)
			{
				if (tile.Color == ConsoleColor.Red)
					tile.Color = ConsoleColor.White;
				else
					tile.Color = ConsoleColor.Red;

				DungeonManager.Instance.ForceRedraw();

				//This code belongs in a method in the GameManger or a future Time Manager
				Timer = GameManager.Instance.Time.ElapsedMilliseconds + delay;
				while (Timer > GameManager.Instance.Time.ElapsedMilliseconds)
				{
					//wait 
				}
			}
		}

		public void ForceFullVisualization(DungeonLevel dungeonLevel)
		{
			Console.Clear();
			Camera.Layer.ClearOldSquares();
			DungeonManager.Instance.DungeonScreen.ReDraw();
			Visualize(dungeonLevel, true);
		}

		private void Draw(DungeonLevel dungeonLevel, Point startPoint)
		{
			Camera.Draw(dungeonLevel, startPoint);
		}
		#endregion

	}
}
